package com.nanhai.buddhist.college.module.study.service.attendancemanagement;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.nanhai.buddhist.college.framework.common.pojo.CommonResult;
import com.nanhai.buddhist.college.framework.common.pojo.PageResult;
import com.nanhai.buddhist.college.framework.common.util.collection.CollectionUtils;
import com.nanhai.buddhist.college.framework.common.util.number.NumberUtils;
import com.nanhai.buddhist.college.module.collegebase.api.collegeclass.CollegeClassApi;
import com.nanhai.buddhist.college.module.collegebase.api.collegeclass.dto.ClassesParentInfoDTO;
import com.nanhai.buddhist.college.module.collegebase.api.student.StudentApi;
import com.nanhai.buddhist.college.module.collegebase.api.student.dto.StudentRespDTO;
import com.nanhai.buddhist.college.module.collegebase.api.teacher.TeacherApi;
import com.nanhai.buddhist.college.module.collegebase.api.teacher.dto.TeacherRespDTO;
import com.nanhai.buddhist.college.module.study.controller.admin.attendancemanagement.vo.AttendanceManagementCreateReqVO;
import com.nanhai.buddhist.college.module.study.controller.admin.attendancemanagement.vo.AttendanceManagementExportReqVO;
import com.nanhai.buddhist.college.module.study.controller.admin.attendancemanagement.vo.AttendanceManagementListReqVO;
import com.nanhai.buddhist.college.module.study.controller.admin.attendancemanagement.vo.AttendanceManagementPageReqVO;
import com.nanhai.buddhist.college.module.study.controller.admin.attendancemanagement.vo.AttendanceManagementRespVO;
import com.nanhai.buddhist.college.module.study.controller.admin.attendancemanagement.vo.AttendanceManagementUpdateReqVO;
import com.nanhai.buddhist.college.module.study.controller.student.attendance.vo.StudentManagementPageReqVO;
import com.nanhai.buddhist.college.module.study.controller.teacher.vo.AttendanceManagementAddReq;
import com.nanhai.buddhist.college.module.study.controller.teacher.vo.AttendanceManagementCheckReqVO;
import com.nanhai.buddhist.college.module.study.controller.teacher.vo.ManagementCheckPageReqVO;
import com.nanhai.buddhist.college.module.study.convert.attendancemanagement.AttendanceManagementConvert;
import com.nanhai.buddhist.college.module.study.dal.dataobject.attendanceleavereason.AttendanceLeaveReasonDO;
import com.nanhai.buddhist.college.module.study.dal.dataobject.attendancemanagement.AttendanceManagementDO;
import com.nanhai.buddhist.college.module.study.dal.dataobject.attendancemanagementlog.AttendanceManagementLogDO;
import com.nanhai.buddhist.college.module.study.dal.mysql.attendancemanagement.AttendanceManagementMapper;
import com.nanhai.buddhist.college.module.study.dal.mysql.attendancemanagementlog.AttendanceManagementLogMapper;
import com.nanhai.buddhist.college.module.study.enums.ClockRoleTypeEnum;
import com.nanhai.buddhist.college.module.study.service.attendanceleavereason.AttendanceLeaveReasonService;
import com.nanhai.buddhist.college.module.study.util.DateConvertUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

import static com.nanhai.buddhist.college.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.nanhai.buddhist.college.module.study.enums.ErrorCodeConstants.ATTENDANCE_MANAGEMENT_NOT_EXISTS;

/**
 * 考勤管理 Service 实现类
 *
 * @author HeShuai
 */
@Service
@Validated
public class AttendanceManagementServiceImpl implements AttendanceManagementService {

    @Resource
    private AttendanceManagementMapper attendanceManagementMapper;
    @Resource
    private StudentApi studentApi;
    @Resource
    private TeacherApi teacherApi;
    @Resource
    private AttendanceLeaveReasonService attendanceLeaveReasonService;
    @Resource
    AttendanceManagementLogMapper attendanceManagementLogMapper;

    @Resource
    private CollegeClassApi collegeClassApi;


    @Override
    public String createAttendanceManagement(AttendanceManagementCreateReqVO createReqVO) {
        // 插入
        AttendanceManagementDO attendanceManagement = AttendanceManagementConvert.INSTANCE.convert(createReqVO);

        // 设置请假人昵称
        setUserName(createReqVO, attendanceManagement);

        // 设置编号
        attendanceManagement.setSerialNumber(NumberUtils.getCodeByServ("SP"));

        attendanceManagementMapper.insert(attendanceManagement);
        // 返回
        return attendanceManagement.getId();
    }

    private void setUserName(AttendanceManagementCreateReqVO createReqVO, AttendanceManagementDO attendanceManagement) {
        if (ClockRoleTypeEnum.STUDENT.getRole().equals(Integer.parseInt(createReqVO.getUserType()))) {
            StudentRespDTO studentRespDTO = studentApi.getStudentRespDTOById(createReqVO.getUserId()).getCheckedData();
            attendanceManagement.setUserName(studentRespDTO.getStudentName());
            attendanceManagement.setCollegeId(studentRespDTO.getCollegesId());
            attendanceManagement.setClassesId(studentRespDTO.getClassesId());
            attendanceManagement.setUserPhone(studentRespDTO.getPhone());
        } else {
            TeacherRespDTO teacherRespDTO = teacherApi.getTeacherById(createReqVO.getUserId()).getCheckedData();
            attendanceManagement.setUserName(teacherRespDTO.getTeacherName());
            attendanceManagement.setCollegeId(teacherRespDTO.getCollegeId());
            attendanceManagement.setUserPhone(teacherRespDTO.getTeacherTelephone());
        }
    }

    @Override
    public void updateAttendanceManagement(AttendanceManagementUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateAttendanceManagementExists(updateReqVO.getId());
        // 更新
        AttendanceManagementDO updateObj = AttendanceManagementConvert.INSTANCE.convert(updateReqVO);
        attendanceManagementMapper.updateById(updateObj);
    }

    @Override
    public void deleteAttendanceManagement(String id) {
        // 校验存在
        this.validateAttendanceManagementExists(id);
        // 删除
        attendanceManagementMapper.deleteById(id);
    }

    private void validateAttendanceManagementExists(String id) {
        if (attendanceManagementMapper.selectById(id) == null) {
            throw exception(ATTENDANCE_MANAGEMENT_NOT_EXISTS);
        }
    }

    @Override
    public AttendanceManagementDO getAttendanceManagement(String id) {
        AttendanceManagementDO attendanceManagementDO = attendanceManagementMapper.selectById(id);
        List<AttendanceManagementDO> list = new ArrayList<>();
        list.add(attendanceManagementDO);
        List<AttendanceManagementDO> attendanceManagementDOS = setAttendanceManagementDOInfo(list);
        return attendanceManagementDOS.get(0);
    }

    @Override
    public List<AttendanceManagementDO> getAttendanceManagementList(Collection<String> ids) {
        return CollectionUtils.isEmpty(ids) ? Collections.emptyList() : attendanceManagementMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<AttendanceManagementDO> getAttendanceManagementPage(AttendanceManagementPageReqVO pageReqVO) {
        PageResult<AttendanceManagementDO> page = attendanceManagementMapper.selectPage(pageReqVO);
        page.setList(setAttendanceManagementDOInfo(page.getList()));
        return page;
    }

    @Override
    public List<AttendanceManagementDO> getAttendanceManagementList(AttendanceManagementExportReqVO exportReqVO) {
        return attendanceManagementMapper.selectList(exportReqVO);
    }

    @Override
    public String createAttendanceManagement(AttendanceManagementAddReq createReqVO) {
        // 插入 AttendanceManagementConvert.INSTANCE.convertAddReq(createReqVO);
        AttendanceManagementDO attendanceManagement = new AttendanceManagementDO();
        BeanUtils.copyProperties(createReqVO, attendanceManagement);
        attendanceManagement.setLeaveEndTime(new Date(Long.parseLong(createReqVO.getLeaveEndTime())));
        attendanceManagement.setLeaveStartTime(new Date(Long.parseLong(createReqVO.getLeaveStartTime())));
        attendanceManagement.setUserType(createReqVO.getUserType() + "");
        // 设置请假人昵称
        if (ClockRoleTypeEnum.STUDENT.getRole().equals(createReqVO.getUserType())) {
            StudentRespDTO studentRespDTO = studentApi.getStudentRespDTOById(createReqVO.getUserId()).getCheckedData();
            attendanceManagement.setUserName(studentRespDTO.getStudentName());
            attendanceManagement.setCollegeId(studentRespDTO.getCollegesId());
            attendanceManagement.setClassesId(studentRespDTO.getClassesId());
            attendanceManagement.setUserPhone(studentRespDTO.getPhone());

        } else {
            TeacherRespDTO teacherRespDTO = teacherApi.getTeacherById(createReqVO.getUserId()).getCheckedData();
            attendanceManagement.setUserName(teacherRespDTO.getTeacherName());
            attendanceManagement.setCollegeId(teacherRespDTO.getCollegeId());
            attendanceManagement.setUserPhone(teacherRespDTO.getTeacherTelephone());
        }
        // 设置编号
        attendanceManagement.setSerialNumber(NumberUtils.getCodeByServ("SP"));
        attendanceManagementMapper.insert(attendanceManagement);
        // 返回
        return attendanceManagement.getId();
    }

    @Override
    @Transactional
    public void checkAttendanceLeave(AttendanceManagementCheckReqVO pageVO) {
        AttendanceManagementDO attendanceManagementDO = attendanceManagementMapper.selectById(pageVO.getId());
        if (ObjectUtil.isNull(attendanceManagementDO)) {
            return;
        }
        //插入审核记录
        addLog(pageVO, attendanceManagementDO);

        attendanceManagementDO.setApprovalStatus(pageVO.getApprovalStatus());
        attendanceManagementDO.setRemark(pageVO.getRemark());
        attendanceManagementMapper.updateById(attendanceManagementDO);


    }

    private void addLog(AttendanceManagementCheckReqVO pageVO, AttendanceManagementDO attendanceManagementDO) {
        AttendanceManagementLogDO logDO = new AttendanceManagementLogDO();
        logDO.setOldStatus(attendanceManagementDO.getApprovalStatus());
        logDO.setNewStatus(pageVO.getApprovalStatus());
        logDO.setCheckRemake(pageVO.getRemark());
        logDO.setManagementId(pageVO.getId());
        logDO.setCheckTime(new Date());
        logDO.setCheckTeacherId(attendanceManagementDO.getCopySendId());
        attendanceManagementLogMapper.insert(logDO);
    }

    @Override
    public List<AttendanceManagementDO> getAttendanceManagementListByQue(AttendanceManagementListReqVO reqVO) {
        LambdaQueryWrapper<AttendanceManagementDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(AttendanceManagementDO::getUserId, reqVO.getUserId())
                .eq(AttendanceManagementDO::getUserType, reqVO.getUserType())
                .eq(ObjectUtil.isNotEmpty(reqVO.getApprovalStatus()), AttendanceManagementDO::getApprovalStatus, reqVO.getApprovalStatus())
                .eq(ObjectUtil.isNotEmpty(reqVO.getReasonId()), AttendanceManagementDO::getReasonId, reqVO.getReasonId());
        return attendanceManagementMapper.selectList(wrapper);
    }

    @Override
    public PageResult<AttendanceManagementDO> getAttendanceManagementPage(StudentManagementPageReqVO req) {

        if (com.xkcoding.http.util.StringUtil.isNotEmpty(req.getLeaveEndTime())) {
            req.setLeaveEndTimeDate(DateConvertUtil.stringToDateEnd(req.getLeaveEndTime()));
        }
        if (com.xkcoding.http.util.StringUtil.isNotEmpty(req.getLeaveStartTime())) {
            req.setLeaveStartTimeDate(DateConvertUtil.stringToDateStart(req.getLeaveStartTime()));
        }
        PageResult<AttendanceManagementDO> page = attendanceManagementMapper.selectPage1(req);
        page.setList(setAttendanceManagementDOInfo(page.getList()));
        return page;
    }

    @Override
    public PageResult<AttendanceManagementDO> getAttendanceManagementCheckPage(ManagementCheckPageReqVO pageVO) {
        PageResult<AttendanceManagementDO> page = attendanceManagementMapper.selectPage2(pageVO);
        page.setList(setAttendanceManagementDOInfo(page.getList()));
        return page;
    }

    @Override
    public PageResult<AttendanceManagementDO> getAttendanceManagementCheckPageApp(ManagementCheckPageReqVO pageVO) {
        PageResult<AttendanceManagementDO> page = attendanceManagementMapper.selectPageApp(pageVO);
        page.setList(setAttendanceManagementDOInfo(page.getList()));
        return page;
    }

    /**
     * 设置返回昵称 学院、请假人昵称、请假人联系方式、请假事由昵称
     *
     * @return
     */
    private List<AttendanceManagementDO> setAttendanceManagementDOInfo(List<AttendanceManagementDO> list) {

        if (CollectionUtil.isEmpty(list)) {
            return list;
        }

        // 学生获取学校等信息
        Set<String> classesIds = CollectionUtils.convertSet(list, AttendanceManagementDO::getClassesId);
        CommonResult<List<ClassesParentInfoDTO>> classesParentInfoDTOByClassesIds = collegeClassApi.getClassesParentInfoDTOByClassesIds(classesIds);
        if (!CollectionUtils.isAnyEmpty(classesParentInfoDTOByClassesIds.getData())) {
            Map<String, ClassesParentInfoDTO> stringClassesParentInfoDTOMap = CollectionUtils.convertMap(classesParentInfoDTOByClassesIds.getData(), ClassesParentInfoDTO::getClassesId);
            list.stream().forEach(s -> {
                s.setCollegeName(Optional.ofNullable(stringClassesParentInfoDTOMap).map(v -> v.get(s.getClassesId())).map(ClassesParentInfoDTO::getCollegeName).orElse(""));
                s.setDepartmentName(Optional.ofNullable(stringClassesParentInfoDTOMap).map(v -> v.get(s.getClassesId())).map(ClassesParentInfoDTO::getDepartmentsName).orElse(""));
                s.setClassesName(Optional.ofNullable(stringClassesParentInfoDTOMap).map(v -> v.get(s.getClassesId())).map(ClassesParentInfoDTO::getClassesName).orElse(""));
            });
        }


        List<String> reasonIds = list.stream().map(AttendanceManagementDO::getReasonId).distinct().collect(Collectors.toList());
        List<AttendanceLeaveReasonDO> leaveReasonList = attendanceLeaveReasonService.getAttendanceLeaveReasonList(reasonIds);
        List<String> teacherIds = list.stream().filter(s -> ClockRoleTypeEnum.TEACHER.getRole().equals(Integer.parseInt(s.getUserType())))
                .map(AttendanceManagementDO::getUserId)
                .distinct().collect(Collectors.toList());
        List<TeacherRespDTO> teacherRespDTOS = new ArrayList<>(teacherIds.size());
        if (CollectionUtil.isNotEmpty(teacherIds)) {
            teacherRespDTOS = teacherApi.getTeacherByIds(teacherIds).getCheckedData();
        }
        final List<TeacherRespDTO> teacherRespDTOList = teacherRespDTOS;
        list.forEach(item -> {
            // 设置事由昵称
            if (CollectionUtil.isNotEmpty(leaveReasonList)) {
                List<AttendanceLeaveReasonDO> collect = leaveReasonList.stream().filter(s -> s.getId().equals(item.getReasonId())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(collect)) {
                    AttendanceLeaveReasonDO attendanceLeaveReasonDO = collect.get(0);
                    item.setReasonName(attendanceLeaveReasonDO.getLeaveReason());
                }
            }

            // 教师查询学院昵称
            if (ClockRoleTypeEnum.TEACHER.getRole().equals(Integer.parseInt(item.getUserType()))
                    && CollectionUtil.isNotEmpty(teacherRespDTOList)) {
                List<TeacherRespDTO> collect = teacherRespDTOList.stream().filter(s -> s.getId().equals(item.getUserId())).collect(Collectors.toList());
                if (CollectionUtil.isNotEmpty(collect)) {
                    TeacherRespDTO teacherRespDTO = collect.get(0);
                    item.setCollegeName(Optional.ofNullable(teacherRespDTO).map(TeacherRespDTO::getCollegeName).orElse(""));
                    item.setHead(Optional.ofNullable(teacherRespDTO).map(TeacherRespDTO::getHeadImage).orElse(""));
                }
            }else {
                 StudentRespDTO data = studentApi.getStudentRespDTOById(item.getUserId()).getData();
                if (ObjectUtil.isNotEmpty(data)) {
                    item.setHead(data.getHeadImage());
                }
            }
        });
        return list;
    }

}
